package net.wantongtech.xa.uploadbasicinfo.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.google.common.io.Files;
import com.wtkj.vo.RandomGUID;
import com.wtkj.vo.dzzf.base.kfwd.CardInfoOpt;
import com.wtkj.vo.dzzf.base.kfwd.PacketCaptureCardOpt;
import com.wtkj.vo.dzzf.share.staticvalue.BusinessType;
import com.wtkj.vo.dzzf.share.staticvalue.CardStaticValue;
import lombok.extern.slf4j.Slf4j;
import net.wantongtech.xa.uploadbasicinfo.dao.PostPoneAnnualTimeDao;
import net.wantongtech.xa.uploadbasicinfo.vo.PostPoneAnnual;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.javatuples.Pair;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 包年卡片有效期顺延服务
 */
@Slf4j
@Service
public class PostPoneAnnualCardTimeService {

    /**
     * 开始免费日期
     */
    private static final LocalDate FREE_START_LOCAL_DATE = LocalDate.parse("2020-02-17");

    public static final Date FREE_START_DATE = FREE_START_LOCAL_DATE.toDate();

    /**
     * 结束免费日期
     */
    public static final LocalDate FREE_END_LOCAL_DATE = LocalDate.parse("2020-05-05");

    public static final Date FREE_END_DATE = FREE_END_LOCAL_DATE.toDate();


    @Resource
    private PostPoneAnnualTimeDao postPoneAnnualTimeDao;

    @Resource
    private ThreadPoolTaskExecutor taskExecutor;

    private final List<Object> errorObjList = Lists.newCopyOnWriteArrayList();

    private final List<PostPoneAnnual> postPoneAnnualList = Lists.newCopyOnWriteArrayList();

    private final ObjectMapper objectMapper = new ObjectMapper();

    public void postPone() {

        List<Pair<Integer, String>> selfCardInfoList = postPoneAnnualTimeDao.queryAllSelfAnnualCardInfo();
        log.info("共查询到{}条包年卡片信息", selfCardInfoList.size());
        selfCardInfoList.forEach(v -> taskExecutor.execute(new ProcessSelfCardRunnable(v)));

        List<Pair<Integer, String>> bankCardInfoList = postPoneAnnualTimeDao.queryAllBankAnnualCardInfo();
        log.info("共查询到{}条包年卡片信息", bankCardInfoList.size());
        bankCardInfoList.forEach(v -> taskExecutor.execute(new ProcessBankCardRunnable(v)));

        try {
            TimeUnit.MINUTES.sleep(1);
        } catch (InterruptedException e) {
            log.error(e.getMessage(), e);
        }

        if (!postPoneAnnualList.isEmpty()) {
            try {
                //noinspection UnstableApiUsage
                Files.write(objectMapper.writeValueAsString(postPoneAnnualList),
                        new File("C:\\temp\\annual\\postpone.json"), StandardCharsets.UTF_8);
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        }


        log.info("共获取到{}条原始交易，错误信息：{}", errorObjList.size(), errorObjList);
    }


    private void processSelfCardInfo(Pair<Integer, String> pair) {
        Integer cardNetId = pair.getValue0();
        String eCardNo = pair.getValue1();
        log.info("待处理卡号：{}", cardNetId + eCardNo);

        List<CardInfoOpt> cardInfoOptList = postPoneAnnualTimeDao.queryAnnualCardInfoOpt(eCardNo);
        log.info("共查询出{}条操作记录", cardInfoOptList.size());

        int size = cardInfoOptList.size();

        int errIdx = 0;
        List<CardInfoOpt> revertObjList = Lists.newArrayList();
        for (CardInfoOpt opt : cardInfoOptList) {
            Integer businessType = opt.getAnnualBusinessType();
            if (businessType == CardStaticValue.AnnualBusiness_Flag.Business_Flag_CX) {
                errIdx = errIdx - 1;
            } else {
                errIdx = errIdx + 1;
            }
            if (errIdx <= 0) {
                revertObjList.add(opt);
            }
        }

        revertObjList.forEach(cardInfoOptList::remove);

        if (cardInfoOptList.isEmpty()) {
            return;
        }

        List<CardInfoOpt> optList = Lists.newArrayList();
        CardInfoOpt firstOpt = cardInfoOptList.get(0);
        Date firstStartOn = firstOpt.getPacketCaptureStartOn();

        String optType = firstOpt.getOptType();
        if (BusinessType.XK.equals(optType) && firstOpt.getAnnualFeeCard() != null
                && firstOpt.getAnnualFeeCard() == CardStaticValue.Annual_Flag.Annual_Flag_NFK) {

            Date optOn = firstOpt.getOptOn();
            if (optOn.compareTo(FREE_START_DATE) < 0 || optOn.compareTo(FREE_END_DATE) > 0) {
                log.info("销卡时间：{}，不在免费区间内", DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.format(optOn));
                return;
            } else {
                firstOpt.setAnnualBusinessType(CardStaticValue.AnnualBusiness_Flag.Business_Flag_QX);
                optList.add(firstOpt);
            }
        } /*else {
            Integer firstAnnualBusinessType = firstOpt.getAnnualBusinessType();
            if (firstAnnualBusinessType != CardStaticValue.AnnualBusiness_Flag.Business_Flag_QX) {

                // 非包年取消 且 启用日期在 2/17 - 5/6 之间
                if (firstStartOn.compareTo(FREE_START_DATE) >= 0 &&
                        firstStartOn.compareTo(FREE_END_DATE) <= 0) {

                    //查询包年取消的前一条记录
                    cardInfoOptList.stream()
                            .filter(v -> !Objects.equals(v, firstOpt) &&
                                    v.getAnnualBusinessType() == CardStaticValue.AnnualBusiness_Flag.Business_Flag_QX &&
                                    v.getOptOn().compareTo(FREE_START_DATE) >= 0)
                            .findFirst().ifPresent(cancelOpt -> cardInfoOptList.stream()
                            .filter(v -> {
                                Date packetCaptureEndOn = v.getPacketCaptureEndOn();
                                return !Objects.equals(v, firstOpt) && !Objects.equals(v, cancelOpt) &&
                                        packetCaptureEndOn.compareTo(FREE_START_DATE) >= 0 &&
                                        packetCaptureEndOn.compareTo(FREE_END_DATE) <= 0 &&
                                        !"1223".equals(v.getOptType());
                            })
                            .findFirst()
                            .ifPresent(v -> {
                                log.info("追溯到取消的包年记录：{}", v);
                                v.setAnnualBusinessType(CardStaticValue.AnnualBusiness_Flag.Business_Flag_QX);
                                v.setOptOn(cancelOpt.getOptOn());
                                optList.add(v);
                            }));
                }

                optList.add(firstOpt);
            } else if (firstOpt.getOptOn().compareTo(FREE_START_DATE) >= 0) {
                cardInfoOptList.stream()
                        .filter(v -> !Objects.equals(v, firstOpt) &&
                                v.getAnnualBusinessType() != CardStaticValue.AnnualBusiness_Flag.Business_Flag_QX)
                        .findFirst()
                        .ifPresent(v -> {
                            v.setOptOn(firstOpt.getOptOn());
                            v.setAnnualBusinessType(CardStaticValue.AnnualBusiness_Flag.Business_Flag_QX);
                            optList.add(v);
                        });
            }
        }*/


        for (CardInfoOpt cardInfoOpt : optList) {

            Date packetCaptureStartOn = cardInfoOpt.getPacketCaptureStartOn();
            Date packetCaptureEndOn = cardInfoOpt.getPacketCaptureEndOn();

            LocalDate captureStartLocalDate = LocalDate.fromDateFields(packetCaptureStartOn);
            LocalDate captureEndLocalDate = LocalDate.fromDateFields(packetCaptureEndOn);

            Integer annualBusinessType = cardInfoOpt.getAnnualBusinessType();

            int preferential = 0;
            //销卡
            if (annualBusinessType == CardStaticValue.AnnualBusiness_Flag.Business_Flag_QX) {

                Date optOn = cardInfoOpt.getOptOn();
                if (optOn.compareTo(packetCaptureEndOn) >= 0) {
                    preferential = Days.daysBetween(FREE_START_LOCAL_DATE, captureEndLocalDate).getDays() + 1;
                } else {
                    preferential = Days.daysBetween(FREE_START_LOCAL_DATE, LocalDate.fromDateFields(optOn)).getDays();
                }

            } else {
                // 2/17前 -  2/17-5/5之间
                if (captureStartLocalDate.compareTo(FREE_START_LOCAL_DATE) <= 0 &&
                        captureEndLocalDate.compareTo(FREE_START_LOCAL_DATE) >= 0 &&
                        captureEndLocalDate.compareTo(FREE_END_LOCAL_DATE) <= 0) {
                    preferential = Days.daysBetween(FREE_START_LOCAL_DATE, captureEndLocalDate).getDays() + 1;
                    // 2/17前 - 5/5之后
                } else if (captureStartLocalDate.compareTo(FREE_START_LOCAL_DATE) <= 0 &&
                        captureEndLocalDate.compareTo(FREE_END_LOCAL_DATE) >= 0) {
                    preferential = Days.daysBetween(FREE_START_LOCAL_DATE, FREE_END_LOCAL_DATE).getDays() + 1;
                    // 2/17 - 5/5之间
                } else if (captureStartLocalDate.compareTo(FREE_START_LOCAL_DATE) >= 0 &&
                        captureStartLocalDate.compareTo(FREE_END_LOCAL_DATE) <= 0) {
                    preferential = Days.daysBetween(captureStartLocalDate, FREE_END_LOCAL_DATE).getDays() + 1;
                }
            }

            PostPoneAnnual annual = new PostPoneAnnual();
            annual.setId(new RandomGUID().toString());
            annual.setCardNetId(cardInfoOpt.getCardNetID());
            annual.setECardNo(cardInfoOpt.geteCardNo());
            annual.setPacketCaptureStartOn(packetCaptureStartOn);
            annual.setPacketCaptureEndOn(packetCaptureEndOn);
            annual.setPacketCaptureRoad(Integer.valueOf(cardInfoOpt.getPacketCaptureRoad()));
            annual.setPreferential(preferential);
            annual.setVehPlate(cardInfoOpt.getVehiclePlate());
            annual.setVehColor(cardInfoOpt.getVehicleColor());
            annual.setState(PostPoneAnnual.NONE);
            annual.setBusinessType(annualBusinessType);
//            postPoneAnnualList.add(annual);
            postPoneAnnualTimeDao.createValueObject(annual);
        }

    }

    private void processBankCardInfo(Pair<Integer, String> pair) {
        Integer cardNetId = pair.getValue0();
        String eCardNo = pair.getValue1();
        log.info("待处理卡号：{}", cardNetId + eCardNo);

        List<PacketCaptureCardOpt> captureCardOptList = postPoneAnnualTimeDao.queryBankAnnualCardInfoOpt(eCardNo);
        int size = captureCardOptList.size();
        log.info("共查询出{}条操作记录", size);


        int errorIdx = 0;
        List<PacketCaptureCardOpt> revertObjList = Lists.newArrayList();
        for (PacketCaptureCardOpt opt : captureCardOptList) {
            Integer businessType = opt.getAnnualBusinessType();
            if (businessType == CardStaticValue.AnnualBusiness_Flag.Business_Flag_CX) {
                errorIdx = errorIdx - 1;
            } else {
                errorIdx = errorIdx + 1;
            }
            if (errorIdx <= 0) {
                revertObjList.add(opt);
            }
        }

        revertObjList.forEach(captureCardOptList::remove);

        if (captureCardOptList.isEmpty()) {
            log.info("无可处理记录");
            return;
        }


        List<PacketCaptureCardOpt> optList = Lists.newArrayList();
        PacketCaptureCardOpt firstOpt = captureCardOptList.get(0);


        Date firstStartOn = firstOpt.getPacketCaptureStartOn();

        String optType = firstOpt.getOptType();
        if (BusinessType.XK.equals(optType)) {
            Date optOn = firstOpt.getOptOn();
            if (optOn.compareTo(FREE_START_DATE) < 0 || optOn.compareTo(FREE_END_DATE) > 0) {
                log.info("销卡时间：{}，不在免费区间内",
                        DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.format(optOn));
                return;
                //销卡时间位于免费区间内
            } else {
                captureCardOptList.stream()
                        .filter(v -> !Objects.equals(v, firstOpt))
                        .findFirst()
                        .ifPresent(v -> {
                            v.setOptOn(firstOpt.getOptOn());
                            v.setAnnualBusinessType(CardStaticValue.AnnualBusiness_Flag.Business_Flag_QX);
                            optList.add(v);
                        });
            }
        } else {

            // 非包年取消 且 启用日期在 2/17 - 5/5 之间
            if (firstOpt.getAnnualBusinessType() != CardStaticValue.AnnualBusiness_Flag.Business_Flag_QX) {

                if (firstStartOn.compareTo(FREE_START_DATE) >= 0 &&
                        firstStartOn.compareTo(FREE_END_DATE) <= 0) {

                    captureCardOptList.stream()
                            .filter(v -> !Objects.equals(v, firstOpt) &&
                                    v.getAnnualBusinessType() == CardStaticValue.AnnualBusiness_Flag.Business_Flag_QX &&
                                    v.getOptOn().compareTo(FREE_START_DATE) >= 0)
                            .findFirst().ifPresent(cancelOpt -> captureCardOptList.stream()
                            .filter(v -> {
                                Date packetCaptureEndOn = v.getPacketCaptureEndOn();
                                return !Objects.equals(v, firstOpt) && !Objects.equals(v, cancelOpt) &&
                                        packetCaptureEndOn.compareTo(FREE_START_DATE) >= 0 &&
                                        packetCaptureEndOn.compareTo(FREE_END_DATE) <= 0 &&
                                        !"1223".equals(v.getOptType());
                            })
                            .findFirst()
                            .ifPresent(v -> {
                                log.info("追溯到取消的包年记录：{}", v);
                                v.setAnnualBusinessType(CardStaticValue.AnnualBusiness_Flag.Business_Flag_QX);
                                v.setOptOn(cancelOpt.getOptOn());
                                optList.add(v);
                            }));
                }
                optList.add(firstOpt);
            } else if (firstOpt.getOptOn().compareTo(FREE_START_DATE) >= 0) {
                captureCardOptList.stream()
                        .filter(v -> !Objects.equals(v, firstOpt) &&
                                v.getAnnualBusinessType() != CardStaticValue.AnnualBusiness_Flag.Business_Flag_QX)
                        .findFirst()
                        .ifPresent(v -> {
                            v.setOptOn(firstOpt.getOptOn());
                            v.setAnnualBusinessType(CardStaticValue.AnnualBusiness_Flag.Business_Flag_QX);
                            optList.add(v);
                        });
            }
        }


        for (PacketCaptureCardOpt packetCaptureCardOpt : optList) {

            Date packetCaptureStartOn = packetCaptureCardOpt.getPacketCaptureStartOn();
            Date packetCaptureEndOn = packetCaptureCardOpt.getPacketCaptureEndOn();

            LocalDate captureStartLocalDate = LocalDate.fromDateFields(packetCaptureStartOn);
            LocalDate captureEndLocalDate = LocalDate.fromDateFields(packetCaptureEndOn);

            Integer annualBusinessType = packetCaptureCardOpt.getAnnualBusinessType();

            int preferential = 0;

            if (annualBusinessType == CardStaticValue.AnnualBusiness_Flag.Business_Flag_QX) {
                Date optOn = packetCaptureCardOpt.getOptOn();
                if (optOn.compareTo(packetCaptureEndOn) >= 0) {
                    preferential = Days.daysBetween(FREE_START_LOCAL_DATE, captureEndLocalDate).getDays() + 1;
                } else {
                    preferential = Days.daysBetween(FREE_START_LOCAL_DATE, LocalDate.fromDateFields(optOn)).getDays() + 1;
                }
            } else {
                // 2/17前 -  2/17-5/5之间
                if (captureStartLocalDate.compareTo(FREE_START_LOCAL_DATE) <= 0 &&
                        captureEndLocalDate.compareTo(FREE_START_LOCAL_DATE) >= 0 &&
                        captureEndLocalDate.compareTo(FREE_END_LOCAL_DATE) <= 0) {
                    preferential = Days.daysBetween(FREE_START_LOCAL_DATE, captureEndLocalDate).getDays() + 1;
                    // 2/17前 - 5/5之后
                } else if (captureStartLocalDate.compareTo(FREE_START_LOCAL_DATE) <= 0 &&
                        captureEndLocalDate.compareTo(FREE_END_LOCAL_DATE) >= 0) {
                    preferential = Days.daysBetween(FREE_START_LOCAL_DATE, FREE_END_LOCAL_DATE).getDays() + 1;
                    // 2/17 - 5/5之间
                } else if (captureStartLocalDate.compareTo(FREE_START_LOCAL_DATE) >= 0 &&
                        captureStartLocalDate.compareTo(FREE_END_LOCAL_DATE) <= 0) {
                    preferential = Days.daysBetween(captureStartLocalDate, FREE_END_LOCAL_DATE).getDays() + 1;
                    // 5/6 ~
                }
            }


            PostPoneAnnual annual = new PostPoneAnnual();
            annual.setId(new RandomGUID().toString());
            annual.setCardNetId(packetCaptureCardOpt.getCardNetID());
            annual.setECardNo(packetCaptureCardOpt.geteCardNo());
            annual.setPacketCaptureStartOn(packetCaptureStartOn);
            annual.setPacketCaptureEndOn(packetCaptureEndOn);
            annual.setPacketCaptureRoad(Integer.valueOf(packetCaptureCardOpt.getPacketCaptureRoad()));
            annual.setPreferential(preferential);
            annual.setVehPlate(packetCaptureCardOpt.getVehiclePlate());
            annual.setVehColor(packetCaptureCardOpt.getVehicleColor());
            annual.setState(PostPoneAnnual.NONE);
            annual.setBusinessType(annualBusinessType);
            postPoneAnnualTimeDao.createValueObject(annual);
        }


    }


    class ProcessSelfCardRunnable implements Runnable {

        private final Pair<Integer, String> pair;

        public ProcessSelfCardRunnable(Pair<Integer, String> pair) {
            this.pair = pair;
        }

        @Override
        public void run() {
            try {
                processSelfCardInfo(pair);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
    }


    class ProcessBankCardRunnable implements Runnable {

        private final Pair<Integer, String> pair;

        public ProcessBankCardRunnable(Pair<Integer, String> pair) {
            this.pair = pair;
        }

        @Override
        public void run() {
            try {
                processBankCardInfo(pair);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
    }

    public static void main(String[] args) {
        System.out.println(Days.daysBetween(LocalDate.parse("2020-02-17"), LocalDate.parse("2020-04-10")).getDays() + 1);
    }

}
